package com.lingyun.framework.security;

import cn.hutool.extra.spring.SpringUtil;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.logout.LogoutFilter;
import org.springframework.security.web.firewall.HttpFirewall;
import org.springframework.security.web.firewall.StrictHttpFirewall;
import org.springframework.web.filter.CorsFilter;

import javax.annotation.Resource;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;


/**
 * security配置类
 *
 * @author 没事别学JAVA
 */
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    //未登陆时返回 JSON 格式的数据给前端（否则为 html）
    @Resource
    AjaxAuthenticationEntryPoint authenticationEntryPoint;

    //登录成功返回的 JSON 格式数据给前端（否则为 html）
    @Resource
    AjaxAuthenticationSuccessHandler authenticationSuccessHandler;

    //登录失败返回的 JSON 格式数据给前端（否则为 html）
    @Resource
    AjaxAuthenticationFailureHandler authenticationFailureHandler;

    //注销成功返回的 JSON 格式数据给前端（否则为 登录时的 html）
    @Resource
    AjaxLogoutSuccessHandler logoutSuccessHandler;

    //无权访问返回的 JSON 格式数据给前端（否则为 403 html 页面）
    @Resource
    AjaxAccessDeniedHandler accessDeniedHandler;

    // token过滤器 验证token有效性
    @Resource
    JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;

    // 自定义认证
    @Resource
    SelfAuthenticationProvider selfAuthenticationProvider;

    //跨域过滤器
    @Resource
    private CorsFilter corsFilter;



    /**
     * anyRequest            匹配所有请求路径
     * access                SpringEl表达式结果为true时可以访问
     * anonymous             匿名可以访问
     * denyAll               用户不能访问
     * fullyAuthenticated    用户完全认证可以访问（非remember-me下自动登录）
     * hasAnyAuthority       如果有参数，参数表示权限，则其中任何一个权限可以访问
     * hasAnyRole            如果有参数，参数表示角色，则其中任何一个角色可以访问
     * hasAuthority          如果有参数，参数表示权限，则其权限可以访问
     * hasIpAddress          如果有参数，参数表示IP地址，如果用户IP和参数匹配，则可以访问
     * hasRole               如果有参数，参数表示角色，则其角色可以访问
     * permitAll             用户可以任意访问
     * rememberMe            允许通过remember-me登录的用户访问
     * authenticated         用户登录后可访问
     */

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        //关闭csrf防护 因为不使用session
        http.csrf().disable();

        http.authorizeRequests()


                .antMatchers("/swagger-ui.html").permitAll()
                .antMatchers("/doc.html").permitAll()
                .antMatchers("/v2/**","/webjars/**").permitAll()
                .antMatchers("/swagger-resources/**").permitAll()

                //放行登录接口  验证码
                .antMatchers("/system/login", "/common/captchaImage").permitAll()
                //放行注册接口-发送邮箱
                .antMatchers("/system/registered/sendemailverificationcode").permitAll()
                //放行注册接口
                .antMatchers("/system/registered/lyregistered").permitAll()

                //临时放行
                .antMatchers("/web/**").permitAll()

                //图片访问接口
                .antMatchers("/ly/ly-images/**").access("permitAll()")
                //其他 url 需要被认证（登录）
                .anyRequest().authenticated();

        //注销
        http.logout()
                //自定义注销接口
                .logoutUrl("/logout")
                //自定义注销成功处理
                .logoutSuccessHandler(logoutSuccessHandler);


        //         用来解决匿名用户访问无权限资源时的异常
        http.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint);
        //         用来解决认证过的用户访问无权限资源时的异常
        http.exceptionHandling().accessDeniedHandler(accessDeniedHandler);


        // 基于token，所以不需要session
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);


        // 添加JWT filter
        http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
        // 添加CORS filter
        http.addFilterBefore(corsFilter, JwtAuthenticationTokenFilter.class);
        http.addFilterBefore(corsFilter, LogoutFilter.class);

        //http.headers().frameOptions().sameOrigin();


    }

    /**
     * 配置认证
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) {
        // 自定义的安全认证
        auth.authenticationProvider(selfAuthenticationProvider);
    }

    /**
     * 加密
     *
     * @return
     */
    @Bean
    public PasswordEncoder getPw() {
        return new BCryptPasswordEncoder();
    }


}
